Naver Login
Naver 集成文档
Naver 为韩国最大搜索引擎公司
https://developers.naver.com/main/
Naver Login 注册和引入
集成文档:https://developers.naver.com/docs/login/android/android.md
My Application 注册
My Application 注册:https://developers.naver.com/apps/#/wizard/register?auth=true
记录:OAUTH_CLIENT_ID、OAUTH_CLIENT_SECRET、OAUTH_CLIENT_NAME
Gradle引入
// groovy
implementation 'com.navercorp.nid:oauth:5.9.0' // jdk 11
implementation 'com.navercorp.nid:oauth-jdk8:5.9.0' // jdk 8
// kts
implementation("com.navercorp.nid:oauth:5.9.0") // jdk 11
implementation("com.navercorp.nid:oauth-jdk8:5.9.0") // jdk 8
Login 代码
initialize
fun init(context: Context) {
NaverIdLoginSDK.initialize(context, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CLIENT_NAME)
}
Login in
登录分为 2 种方式:
- NidOAuthLoginButton
- NaverIdLoginSDK.authenticate()
NidOAuthLoginButton
- xml
<com.navercorp.nid.oauth.view.NidOAuthLoginButton
android:id="@+id/buttonOAuthLoginImg"
android:layout_width="wrap_content"
android:layout_height="50dp" />
- code
binding.buttonOAuthLoginImg.setOAuthLogin(launcher)
// OR
binding.buttonOAuthLoginImg.setOAuthLogin(oauthLoginCallback)
NaverIdLoginSDK.authenticate()
object NaverHelper {
private const val TAG = "hacket.naver"
const val OAUTH_CLIENT_ID = "AEhmbl_uDX5pCOSIIRiq"
const val OAUTH_CLIENT_SECRET = "VGZ5lyXLUv"
const val OAUTH_CLIENT_NAME = "KingAssistant"
fun init(context: Context) {
NaverIdLoginSDK.showDevelopersLog(BuildConfig.DEBUG)
NaverIdLoginSDK.initialize(context, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CLIENT_NAME)
}
fun login(
context: Context,
onSuccess: (NaverLoginAuthInfo?, NidProfile?) -> Unit = { _, _ -> },
onFailure: (String?, String?) -> Unit = { _, _ -> }
) {
val oauthLoginCallback = object : OAuthLoginCallback {
override fun onSuccess() {
// 네이버 로그인 인증이 성공했을 때 수행할 코드 추가
getProfile(
{
val loginAuthInfo = getLoginAuthInfo()
onSuccess.invoke(loginAuthInfo, it)
}
) { err, msg ->
onFailure.invoke(err.toString(), msg)
}
}
override fun onFailure(httpStatus: Int, message: String) {
val errorCode = NaverIdLoginSDK.getLastErrorCode().code
val errorDescription = NaverIdLoginSDK.getLastErrorDescription()
Toast.makeText(
context,
"errorCode:$errorCode, errorDesc:$errorDescription",
Toast.LENGTH_SHORT,
).show()
onFailure.invoke(errorCode, errorDescription)
}
override fun onError(errorCode: Int, message: String) {
onFailure(errorCode, message)
}
}
NaverIdLoginSDK.authenticate(context, oauthLoginCallback)
}
fun getLoginAuthInfo(): NaverLoginAuthInfo {
return NaverLoginAuthInfo(
NaverIdLoginSDK.getAccessToken(),
NaverIdLoginSDK.getRefreshToken(),
NaverIdLoginSDK.getExpiresAt(),
NaverIdLoginSDK.getTokenType(),
NaverIdLoginSDK.getState(),
)
}
/**
* Profile API call
*
* https://developers.naver.com/docs/login/android/android.md#9--%ED%94%84%EB%A1%9C%ED%95%84-api-%ED%98%B8%EC%B6%9C
*/
fun getProfile(
onSuccess: (NidProfile?) -> Unit = {},
onFailure: (Int, String) -> Unit = { _, _ -> }
) {
NidOAuthLogin().callProfileApi(object : NidProfileCallback<NidProfileResponse> {
override fun onError(errorCode: Int, message: String) {
onFailure(errorCode, message)
}
override fun onFailure(httpStatus: Int, message: String) {
onFailure(httpStatus, message)
}
override fun onSuccess(result: NidProfileResponse) {
onSuccess(result.profile)
}
})
// 返回的是Map结构
// NidOAuthLogin().getProfileMap(nidProfileCallback)
}
/**
* Log out
*
* When the method is called, the token stored on the client is deleted
*
* 如果网络不行的只会删除本地的token
*
* https://developers.naver.com/docs/login/android/android.md#7--%EB%A1%9C%EA%B7%B8%EC%95%84%EC%9B%83
*/
fun logout() {
NaverIdLoginSDK.logout()
}
/**
* Unlink
*
* When you unlink, both the tokens stored on the client and the tokens stored on the server will be deleted.
*
* 会删除本地和服务器的token
*
* https://developers.naver.com/docs/login/android/android.md#8--%EC%97%B0%EB%8F%99-%ED%95%B4%EC%A0%9C
*/
fun unlink(
onSuccess: () -> Unit = {},
onFailure: (Int, String) -> Unit = { _, _ -> }
) {
NidOAuthLogin().callDeleteTokenApi(object : OAuthLoginCallback {
override fun onSuccess() {
// 서버에서 토큰 삭제에 성공한 상태입니다.
onSuccess.invoke()
}
override fun onFailure(httpStatus: Int, message: String) {
// 서버에서 토큰 삭제에 실패했어도 클라이언트에 있는 토큰은 삭제되어 로그아웃된 상태입니다.
// 클라이언트에 토큰 정보가 없기 때문에 추가로 처리할 수 있는 작업은 없습니다.
onFailure(httpStatus, message)
loge("errorCode: ${NaverIdLoginSDK.getLastErrorCode().code}: ${NaverIdLoginSDK.getLastErrorDescription()}")
}
override fun onError(errorCode: Int, message: String) {
// 서버에서 토큰 삭제에 실패했어도 클라이언트에 있는 토큰은 삭제되어 로그아웃된 상태입니다.
// 클라이언트에 토큰 정보가 없기 때문에 추가로 처리할 수 있는 작업은 없습니다.
onFailure(errorCode, message)
}
})
}
fun loge(msg: String, e: Throwable? = null) {
Log.e(TAG, msg, e)
}
fun logi(msg: String) {
Log.i(TAG, msg)
}
fun logd(msg: String) {
Log.d(TAG, msg)
}
}
data class NaverLoginAuthInfo(
val accessToken: String?,
val refreshToken: String?,
val expire: Long?,
val type: String?,
val state: NidOAuthLoginState?,
)
NaverIdLoginSDK.authenticate()获取到 accessToken- 通过
callProfileApi获取到 NidProfile 的 id,传给中间层登录
Naver SDK 评估
背景
亚洲站点、韩国市场,添加三方登录 Naver
版本分析
新接入的 sdk,没有历史接入版本
影响范围
新功能,功能异常情况下会影响到 Naver 用户的三方登录,需要做 abt 降级
价值评估
提升亚洲站点、韩国市场用户登录转化率
影响评估
App 质量
- 存在 4 个 bug 相关的 issues
- 未发现有 ANR 的 issues
性能
待测试
包大小
- aar 大小 (
com.navercorp.nid:oauth:5.9.0) 226KB

- 文档很久未更新,国际化适配做的不好
兼容性
- SDK 最低版本兼容到 21,和 shein app 最低版本一致
- 其他兼容问题待测试
业务功能影响
新功能,功能异常情况下会影响到 Naver 用户的三方登录,需要做 abt 降级
技术方案评估
6.1 UI、UE
无影响
6.2 接口
无影响
6.3 效果监控
不实施
风险评估
7.1 电子应用市场审核规则风险评估
待评估
7.2 安全评估
- 获取用户的 email, phone,隐私协议是否需要更新?
7.3 降级方案
隐藏 Naver 登录方式